(function($) {

	KOR.suggest = function(selector, mixin) {
		return KOR.Suggest.getInstanceOf(selector, mixin);
	};

	KOR.Suggest = KOR.createClass(KOR.LazyObject, {

		NAME: 'suggest',

		/**
		 * The name of the GET parameter that will hold the value of the input element. If you set this to false the autocompleter will add the value of the input field directly to the url.
		 */
		paramName: 'q',
		/**
		 * This class will be added to the input box.
		 */
		inputClass: "active",
		/**
		 * The class for the UL that will contain the result items (result items are LI elements).
		 */
		resultsClass: "active",
		/**
		 * The class for the input box while results are being fetched from the server.
		 */
		loadingClass: "acLoading",
		/**
		 * The character that separates lines in the results from the backend.
		 */
		lineSeparator: "\n",
		/**
		 * The character that separates cells in the results from the backend.
		 */
		cellSeparator: "|",
		/**
		 * The minimum number of characters a user has to type before the autocompleter activates.
		 */
		minChars: 1,
		/**
		 * The delay in milliseconds the autocompleter waits after a keystroke to activate itself.
		 */
		delay: 400,
		/**
		 * The number of backend query results to store in cache. If set to 1 (the current result), no caching will happen. Do not set below 1.
		 */
		cacheLength: 1,
		/**
		 * Whether or not the autocompleter can use a cache for more specific queries.
		 * This means that all matches of "foot" are a subset of all matches for "foo".
		 * Usually this is true, and using this options decreases server load and increases performance.
		 * Remember to set cacheLength to a bigger number, like 10.
		 */
		matchSubset: false,
		/**
		 * Whether or not the comparison is case sensitive. Only important only if you use caching.
		 */
		matchCase: 0,
		/**
		 * Whether or not the comparison looks inside (i.e. does "ba" match "foo bar") the search results. Only important if you use caching.
		 */
		matchInside: true,
		/**
		 * If set to 1 (true), the autocompleter will only allow results that are presented by the backend.
		 * Note that illegal values result in an empty input box.
		 * In the example at the beginning of this documentation, typing "footer" would result in an empty input box.
		 */
		mustMatch: 0,
		/**
		 * Extra parameters for the backend. If you were to specify { bar:4 }, the autocompleter would call my_autocomplete_backend.php?q=foo&bar=4 (assuming the input box contains "foo").
		 */
		extraParams: {},
		/**
		 * If this is set to true, the first autocomplete value will be automatically selected on tab/return, even if it has not been handpicked by keyboard or mouse action.
		 * If there is a handpicked (highlighted) result, that result will take precedence.
		 */
		selectFirst: false,
		/**
		 * If this is set to true, and there is only one autocomplete when the user hits tab/return, it will be selected even if it has not been handpicked by keyboard or mouse action. This overrides selectFirst.
		 */
		selectOnly: false,
		topOffset: 1,
		/**
		 * A JavaScript funcion that can provide advanced markup for an item.
		 * For each row of results, this function will be called. The returned value will be displayed inside an LI element in the results list.
		 * Autocompleter will provide 3 parameters: the results row, the position of the row in the list of results, and the number of items in the list of results.
		 * See the source code of http://www.dyve.net/jquery?autocomplete for an example.
		 */
		formatItem: null,
		/**
		 * A JavaScript funcion that will be called when an item \nis selected.
		 * The autocompleter will specify a single argument, being the LI element selected.
		 * This LI element will have an attribute "extra" that contains an array of all cells that the backend specified.
		 * See the source code of http://www.dyve.net/jquery?autocomplete for an example.
		 */
		onItemSelect: null,
		data: null,
		initCallback: false,
		url: null,
		/**
		 * Private: for interal use only!!!
		 **/
		parsedData: null,
		displayValue: false,
		showResult: false,
		autoSetWidth: true,

		/**
		 * Creates an instance of the Component based on the selector that created this wrapper.
		 *
		 * @param event
		 * @param data
		 * @returns
		 */
		initAction: function(node, event, data) {
			var obj = this;
			obj.url = obj.url || node.attr('data-suggestURL')
			if(obj.url){
				obj.initAutoComplete(node);
			}
			else if(obj.data && $.type(obj.data) == 'function'){
				obj.data(function(data){
					obj.parsedData = data;
					obj.initAutoComplete(node);
				});
			}
			else if(obj.data && $.type(obj.data) == 'array'){
				obj.parsedData = data;
				obj.initAutoComplete(node);
			}
			return true
		},

		initAutoComplete: function(node){
			var obj = this;
			node.autocomplete({
				url: obj.url,
				data: obj.parsedData,
				paramName: obj.paramName,
				inputClass: obj.inputClass,
				resultsClass: obj.resultsClass,
				loadingClass: obj.loadingClass,
				lineSeparator: obj.lineSeparator,
				cellSeparator: obj.cellSeparator,
				minChars: obj.minChars,
				delay: obj.delay,
				cacheLength: obj.cacheLength,
				matchSubset: obj.matchSubset,
				matchCase: obj.matchCase,
				mustMatch: obj.mustMatch,
				extraParams: obj.extraParams,
				selectFirst: obj.selectFirst,
				selectOnly: obj.selectOnly,
				topOffset: obj.topOffset,
				formatItem: obj.formatItem,
				onItemSelect: obj.onItemSelect,
				displayValue: obj.displayValue,
				matchInside: obj.matchInside,
				showResult: obj.showResult,
				autoSetWidth: obj.autoSetWidth
			});
		}
	});

})(jQuery);
